/*
	This file is part of PropExtractor.

	AliceDecrypt is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	AliceDecrypt is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with PropExtractor. If not, see <http://www.gnu.org/licenses/>.
*/

#include "PropExtractor.h"

// ================================
// Application
// ================================

using namespace pe;

int main(int argc, char** argv)
{
	// get working directory

	char dir[_MAX_PATH];
	GetModuleFileNameA(NULL, dir, _MAX_PATH);
	char* lastslash = strrchr(dir, '\\');
	char workingdir[_MAX_PATH];
	strncpy(workingdir, dir, lastslash - dir + 1);
	workingdir[lastslash - dir + 1] = 0;

	if (argc > 1)
	{
		bool cmd_info = false;
		bool cmd_workingdir = false;
		bool cmd_extract = false;
		bool cmd_extract_all = false;
		unsigned int cmd_extract_index = 0;
		bool cmd_decompress = false;
		bool cmd_decompress_all = false;
		unsigned int cmd_decompress_index = 0;
		char* pattern = NULL;

		if (argc > 2)
		{
			for (int i = 1; i < argc - 1; i++)
			{
				const char* found = strchr(argv[i], '-');
				if (found != NULL)
				{
					switch(argv[i][1])
					{
					case 'i':
						{
							cmd_info = true;
							break;
						}

					case 'w':
						{
							cmd_workingdir = true;
							break;
						}

					case 'e':
						{
							cmd_extract = true;
							const char* next_cmd = strchr(argv[i + 1], '-');
							if (next_cmd != NULL) 
							{ 
								cmd_extract_all = true; 
							}
							else
							{
								cmd_extract_index = atoi(argv[++i]);
							}

							break;
						}

					case 'd':
						{
							cmd_decompress = true;

							const char* next_cmd = strchr(argv[i + 1], '-');
							if (next_cmd != NULL) 
							{
								cmd_decompress_all = true; 
							}
							else
							{
								cmd_decompress_index = atoi(argv[++i]);
							}

							break;
						}

					case 'p':
						{
							const char* next_cmd = strchr(argv[i + 1], '-');
							if (next_cmd != NULL)
							{
								ALICE_PRINT("ERROR! Pattern without string detected.");
							}
							else
							{
								i++;
								pattern = new char[strlen(argv[i]) + 1];
								strcpy(pattern, argv[i]);

								ALICE_DEBUG("Pattern: %s", pattern);
							}

							break;
						}

					default:
						{
							ALICE_PRINT("Unknown argument: %s", argv[i]);
							break;
						}
					}
				}
			}
		}
		else
		{
			FILE* handle = fopen(argv[1], "rb");
			if (!handle) { return 0; }

			char ident[4];
			fread(ident, 1, 4, handle);
			int type = 0;

			if (ident[0] == 'Q' && ident[1] == 'N' && ident[2] == 'T')
			{
				type = 1;
			}
			else if (ident[0] == 'A' && ident[1] == 'A' && ident[2] == 'R')
			{
				type = 2;
			}
			fclose(handle);
			if (type == 0)
			{
				ALICE_PRINT("ERROR! Unknown filetype.");

				system("pause");
				return 0;
			}

			if (type == 1)
			{
				ALICE_PRINT("Loading image '%s'...", argv[1]);

				PEFile read;
				PEFileOpen(&read, argv[1]);

				AliceImageHeader header;
				if (AliceImageReadHeader(&header, &read) != 0) 
				{
					ALICE_PRINT("ERROR! Not an AliceSoft compressed image.");
					system("pause");
					return 0; 
				}

				PEImageRaw raw;
				AliceImageDecompress(&raw, &header, &read);

				PEImageRawSaveToTGA(&raw, read.path);

				ALICE_PRINT("Saved decompressed image to '%s.tga'.", read.path);

				system("pause");
				return 0;
			}
			else if (type == 2)
			{
				ALICE_PRINT("Loading zip '%s'...", argv[1]);

				PEFile file_handle;
				PEFileOpen(&file_handle, argv[1]);

				AliceZip zip_handle;
				if (AliceZipReadHeader(&zip_handle, &file_handle) != 0)
				{
					ALICE_PRINT("ERROR! Not an AliceSoft zip file.");

					system("pause");
					return 0;
				}

				for (unsigned int i = 0; i < zip_handle.files_total; i++)
				{
					ALICE_PRINT("Extracting '%s'...", zip_handle.files[i].path);
					AliceZipExtractFile(&zip_handle, i);
				}

				ALICE_PRINT("Extracted %i files.", zip_handle.files_total);

				system("pause");
				return 0;
			}
		}

		char argument_file[_MAX_PATH];
		if (cmd_workingdir)
		{
			strcpy(argument_file, workingdir);
			strcat(argument_file, argv[argc - 1]);
		}
		else
		{
			strcpy(argument_file, argv[argc - 1]);
		}

		PEFile file_handle;
		if (cmd_info || cmd_decompress || cmd_extract)
		{			
			if (PEFileOpen(&file_handle, argument_file) != 0)
			{
				ALICE_PRINT("ERROR! Couldn't open file.");
				return 0;
			}
		}

		if (cmd_info)
		{
			while (1)
			{
				AliceZip zip_handle;
				if (AliceZipReadHeader(&zip_handle, &file_handle) == 0)
				{
					ALICE_PRINT("AliceSoft zip file");
					ALICE_PRINT("-------------------------");
					ALICE_PRINT("Files: %i", zip_handle.files_total);
					ALICE_PRINT("-------------------------");
					ALICE_PRINT("Structure:");

					for (unsigned int i = 0; i < zip_handle.files_total; i++)
					{
						ALICE_PRINT("(%03i) - %s", i, zip_handle.files[i].path);
					}

					break;
				}

				AliceImageHeader image_handle;
				if (AliceImageReadHeader(&image_handle, &file_handle) == 0)
				{
					ALICE_PRINT("AliceSoft image file");
					ALICE_PRINT("-------------------------");
					ALICE_PRINT("Width: %i", image_handle.width);
					ALICE_PRINT("Height: %i", image_handle.height);
					ALICE_PRINT("Bits per pixel: %i", image_handle.bpp);
					ALICE_PRINT("-------------------------");

					break;
				}

				ALICE_PRINT("Unrecognized file.");
				break;
			}
		}

		if (cmd_extract)
		{
			ALICE_DEBUG("Extracting...");

			while (1)
			{
				AliceZip zip_handle;
				if (AliceZipReadHeader(&zip_handle, &file_handle) != 0)
				{
					ALICE_PRINT("ERROR! Not an AliceSoft zip file.");
					break;
				}

				if (cmd_extract_all)
				{
					for (unsigned int i = 0; i < zip_handle.files_total; i++)
					{
						AliceZipExtractFile(&zip_handle, i);
					}

					ALICE_PRINT("Extracted %i files.", zip_handle.files_total);
				}
				else
				{
					ALICE_DEBUG("Index: %i", cmd_extract_index);
					AliceZipExtractFile(&zip_handle, cmd_extract_index);
					ALICE_PRINT("Extracted '%s'.", zip_handle.files[cmd_extract_index].path);
				}

				break;
			}
		}


		if (cmd_decompress)
		{
			while (1)
			{
				AliceZip zip_handle;
				if (AliceZipReadHeader(&zip_handle, &file_handle) != 0)
				{
					ALICE_PRINT("ERROR! Not an AliceSoft zip file.");
					break;
				}

				if (cmd_decompress_all)
				{
					unsigned int count = 0;
					for (unsigned int i = 0; i < zip_handle.files_total; i++)
					{
						if (AliceZipSaveImageToFile(&zip_handle, i, pattern) == 0) { count++; }
					}

					ALICE_PRINT("Decompressed (%i / %i) files.", count, zip_handle.files_total);
				}
				else
				{
					if (AliceZipSaveImageToFile(&zip_handle, cmd_decompress_index, pattern) == 0)
					{
						char path[_MAX_PATH];
						size_t path_len;
						GetPatternedPath(path, &path_len, pattern, file_handle.path, zip_handle.workingdir, cmd_decompress_index);
						ALICE_PRINT("Decompressed to '%s'.", path);
					}
					else
					{
						ALICE_PRINT("ERROR! Unhandled file type.");
					}
				}

				break;
			}
		}
	}
	else
	{
		// open file

		PEFile read;
		PEFileOpen(&read, "D:\\Projects\\AliceDecrypt\\Data\\PolyData\\Etc\\takarabako\\takarabako.POL");

		AliceModelZippedHeader header;
		AliceZippedModelReadHeader(&header, &read);

		AliceModelData data;
		AliceZippedModelDecompress(&data, &header, &read);

		AliceModel model;
		AliceModelDecrypt(&model, &data);

		AliceSaveModelToObj(&model, "takarabako.POL");

		int i = 0;

		/*
		ALICE_PRINT("AliceDecrypt 0.1\n");
		ALICE_PRINT("Usage: AliceDecrypt.exe <flags> \"<file>\"\n");
		ALICE_PRINT("-i - print info about a file");
		ALICE_PRINT("-w - set working directory to executable's folder");
		ALICE_PRINT("-e - extract file(s) from archive, if no index is supplied, all files are extracted");
		ALICE_PRINT("-d - extract and decompress image(s) from archive, if no index is supplied, all files are decompressed");
		ALICE_PRINT("-p - set pattern to string (%%workingdir%%, %%dir%%, %%name%%, %%ext%%, %%index%%)");
		ALICE_PRINT("\nExamples:\n");
		ALICE_PRINT("Print info about files in an archive.\nAliceDecrypt.exe -i \"archive.red\"\n");
		ALICE_PRINT("Extract file 130 from an archive.\nAliceDecrypt.exe -e 130 \"archive.red\"\n");
		ALICE_PRINT("Decompress all images from an archive.\nAliceDecrypt.exe -p \"%%workingdir%%%%name%%_%%index%%\" -e \"archive.red\"\n");
		*/
	}

	system("pause");

	return 0;
}